return function(BOXUI)

local utils = BOXUI.utils

local includes = utils.includesPoint
local intersects = utils.intersectsRect
local newbox = utils.newbox
local setbox = utils.setbox

local M = utils.newclass("panel")

M.init = function(self, x, y, width, height)
	x, y = (x or 0), (y or 0)
	width  = width  or love.graphics.getWidth()
	height = height or love.graphics.getHeight()
	
	self.theme = BOXUI.theme
	self.x, self.y = x, y
	self.width, self.height = width, height
	
	self.active = nil
	self.objects = {}
	self.mousepresses = {} -- track pressed buttons

	self.viewport = newbox("viewport", 0, 0, width, height)
end

M.find = function(self, object)
	local objects = self.objects
	for i, v in ipairs(objects) do
		if v == object then return i end
	end
end

M.remove = function(self, index)
	local object = self.objects[index]
	object.parent = nil
	if index == self.active then self.active = nil end

	table.remove(self.objects, index)
	if self.onRemove then self:onRemove(object) end
end

M.insert = function(self, object, index)
	local objects = self.objects
	object.parent = self
	if not index then return table.insert(objects, object) end
	print("inserting:", index)
	table.insert(objects, index, object)
end

M.maketop = function(self, index)
	local objects = self.objects
	if not index or index == #objects then return end
	table.insert(objects, objects[index])
	table.remove(objects, index)
end

M.wheelmoved = function(self, wx, wy)
	local active = self.active
	if active then return self.objects[active]:wheelmoved(wx, wy) end
end

M.mousemoved = function(self, x, y, dx, dy)
	local objects = self.objects
	local top = #objects
	if top == 0 then return end
	local relx, rely = x - self.x, y - self.y
	if objects[top].dragging then
		--self.dragging = true
		return objects[top]:mousemoved(relx, rely, dx, dy)
	end
	
	local prevactive, active = self.active, nil
	for i = top, 1, -1 do
		if includes(objects[i], relx, rely) then active = i; break end
	end
	self.active = active
	
	prevactive, active = objects[prevactive], objects[active]
	if prevactive ~= active then
		if prevactive and prevactive.unfocus then prevactive:unfocus() end
		if active and active.focus then active:focus() end
	end
	
	if active then
		return active:mousemoved(relx, rely, dx, dy)
	end
	
	objects[top]:mousemoved(relx, rely, dx, dy) 
end

M.mousepressed = function(self, x, y, button)
	local objects = self.objects
	if #objects == 0 or not self.active then return end
	
	local active = objects[self.active]
	if active.movable and self.active ~= #objects then -- make active top object
		table.remove(objects, self.active)
		table.insert(objects, active)
		self.active = #objects
	end
	active:mousepressed(x - self.x, y - self.y, button)
	
	local waiters = self.mousepresses[button] or {}
	table.insert(waiters, active)
	self.mousepresses[button] = waiters
	
end

M.mousereleased = function(self, x, y, button)
	local waiters = self.mousepresses[button]
	if not waiters then return end -- prank call
	
	local objects = self.objects
	if #objects == 0 then return end

	local relx, rely = x - self.x, y - self.y
	
	for i, v in ipairs(waiters) do
		v:mousereleased(relx, rely, button)
	end
	self.mousepresses[button] = nil
	
	local dragged = objects[#objects].dragging
	if dragged then
		--self.dragging = false
		self:mousemoved(relx, rely, 0, 0)
	end
end

M.update = function(self, dt)
	local objects = self.objects
	if #objects == 0 or not self.active then return end
	objects[self.active]:update(dt)
end

M.draw = function(self, x, y)
	local vp = self.viewport
	x, y = self.x - vp.x + (x or 0), self.y - vp.y + (y or 0)
	
	local theme = self.theme
	local bt = theme.borderThickness
	local color = theme.borderFore
	
	love.graphics.setColor(theme.panelBack)
	--love.graphics.setLineWidth(2)
	love.graphics.rectangle("fill", x + bt, y + bt, self.width - 2 * bt , self.height - 2 * bt)

	local objects = self.objects
	for i, v in ipairs(objects) do
		if v.draw and intersects(v, 0, 0, self.width, self.height) then
			v:draw(x, y)
		end
	end
end


local dummyf = function() end
--M.refresh = dummyf
--M.expand = dummyf
--M.redraw = dummyf
--M.updateViewport = dummyf
--M.focus = dummyf
--M.unfocus = dummyf

M.expand = function(self, width, height)
	self.width, self.height = width, height
end

M.updateViewport = function(self, vpx, vpy, vpw, vph)
	setbox(self.viewport, vpx, vpy, vpw, vph)
end


BOXUI.add(M)
end

